﻿using System.Collections.Generic;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Xml;
using System.Text;
using System.IO;

namespace PlanningGIS.Statistics
{
    /// <summary>
    /// 定义统计字段的属性，key属性的值表示报表对应的字段；
    /// value的属性值表示当前字段对应的名称；type的属性值表示字段类型；
    /// desc属性值表示其描述信息，便于理解，无特别实际意义。
    /// </summary>
    public class ReportField
    {
        private string key;
        private string desc;
        private string value;
        private string type;

        public ReportField()
        {
        }

        public ReportField(string key, string desc, string value, string type)
        {
            this.key = key;
            this.desc = desc;
            this.value = value;
            this.type = type;
        }

        public string Key
        {
            get { return key; }
            set { key = value; }
        }

        public string Desc
        {
            get { return desc; }
            set { desc = value; }
        }

        public string Value
        {
            get { return this.value; }
            set { this.value = value; }
        }

        public string Type
        {
            get { return type; }
            set { type = value; }
        }
    }

    /// <summary>
    /// 根据分类代码指定相应的分类依据
    /// </summary>
    public class StatCode
    {
        private string fcode;     //分类代码
        private string value;     //分类代码对应的分类依据
        private bool check;

        public StatCode()
        {
        }

        public string Fcode
        {
            get { return fcode; }
            set { fcode = value; }
        }

        public string Value
        {
            get { return this.value; }
            set { this.value = value; }
        }

        public bool Check
        {
            get { return check; }
            set { check = value; }
        }

    }

    public class ReportName
    {
        private string key;
        private string value;
        private bool check;
        private bool display;

        public ReportName()
        {
        }

        public string Key
        {
            get { return key; }
            set { key = value; }
        }

        public string Value
        {
            get { return this.value; }
            set { this.value = value; }
        }

        public bool HasParameter
        {
            get { return check; }
            set { check = value; }
        }

        public bool Display
        {
            get { return display; }
            set { display = value; }
        }

    }

    /// <summary>
    /// 定义需要统计的层
    /// </summary>
    public class StatLayer
    {
        private string key;                    //层的唯一标识
        private string value;                 //实际层名
        private List<ReportField> fields;       //需要统计的字段
        private List<StatCode> codes;         //根据分类代码指定相应的分类依据
        private string strCode="FCODE";
        private List<ReportName> reports;

        public StatLayer()
        {
        }

        public StatLayer(string layername, string value, List<ReportField> fields, List<StatCode> codes)
        {
            this.key = layername;
            this.value =value;
            this.fields =fields;
            this.codes = codes;
        }

        public  string LayerName
        {
            get { return key; }
            set { key = value; }
        }

        public string Value
        {
            get {return this.value;}
            set {this.value =value;}
        }

        public List<ReportField> ReportFields
        {
            get {return fields;}
            set {fields =value;}
        }

        public List<ReportName> ReportNames
        {
            get { return reports; }
            set { reports = value; }
        }

        public List<StatCode> StatCodes
        {
            get { return codes; }
            set { codes = value; }
        }

        public string StatFieldName
        {
            get { return strCode; }
            set { strCode = value; }
        }

        public string WhereClause()
        {
            if(codes==null || codes.Count ==0)
            {
                 return null;
            }
            string strClause = null;
            if (strCode == null)
            {
                strCode = "FCODE";
            }
            for (int i = 0; i < codes.Count; i++)
            {
                strClause += " or "+strCode+"='" + codes[i].Fcode+"'";
                
            }
            if (strClause.StartsWith(" or "))
            {
                strClause = strClause.Substring(4);
            }
            return strClause;
        }

        public string WhereClause1()
        {
            if (codes == null || codes.Count == 0)
            {
                return null;
            }
            string strClause = null;
            StringBuilder strBuilder = new StringBuilder();
            foreach (StatCode code in codes)
            {
                if (code.Check)
                {
                    strBuilder.Append(" or " + strCode + "='" + code.Fcode + "'");
                }
            }
            strClause = strBuilder.ToString();
            if (strClause.StartsWith(" or "))
            {
                strClause = strClause.Substring(4);
            }
            return strClause;
        }
    }

    public static  class StatFactory
    {
        /// <summary>
        /// 根据需要统计层的描述内容获取整个层统计信息，包括层名、相应的统计字段
        /// </summary>
        /// <param name="strDesc"></param>
        /// <returns></returns>
        public static  StatLayer GetLayerByID(string stID)
        {
            StatLayer pLyr=new StatLayer();
            XmlDocument doc = new XmlDocument();
            doc.Load(Application.StartupPath + "\\Config\\StatConfig.xml");
            XmlNode  pNode = GetElementByIdname(stID,doc );
            if (pNode == null)     { return null; }
            pLyr.Value = pNode.Attributes["Value"].Value;
            if (!pNode.HasChildNodes)     { return pLyr; }
    
            for(int i=0;i<pNode.ChildNodes.Count ;i++)
            {
                XmlNode pSubNode=pNode.ChildNodes.Item(i);
                switch(pSubNode.Name )
                {
                    case "ReportFields":
                        string strCode = null;
                        pLyr.ReportFields = GetReportfields(pSubNode, out  strCode);
                        pLyr.StatFieldName = strCode;
                        break; 
                    case "Codes":
                        pLyr.StatCodes = GetStatcodes(pSubNode);
                        break;
                    case "StatField":
                        pLyr.StatFieldName = pSubNode.Attributes["Key"].Value;
                        break;
                    case "Reports":
                        pLyr.ReportNames = GetReportnames(pSubNode);
                        break;
                    default:
                        break;
                }
            }
            return pLyr;
        }

        public static List<StatLayer> GetLayersByConfigxml(string strPath)
        {
            List<StatLayer> pLyrs = new List<StatLayer>();
            if (strPath == null || strPath.Length == 0||!File.Exists(strPath))
            {
                return pLyrs;
            }
            try
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(strPath);
                XmlNodeList pNodes = doc.SelectNodes("Stat/LayerName");
                if (pNodes == null || pNodes.Count == 0)
                {
                    return pLyrs;
                }
                for (int i = 0; i < pNodes.Count; i++)
                {
                    XmlNode pNode = pNodes.Item(i);
                    StatLayer pLyr = new StatLayer();
                    pLyr.Value = pNode.Attributes["Value"].Value.Trim();
                    pLyr.LayerName = pNode.Attributes["Key"].Value.Trim();
                    if (!pNode.HasChildNodes) { continue; ; }

                    for (int j = 0; j < pNode.ChildNodes.Count; j++)
                    {
                        XmlNode pSubNode = pNode.ChildNodes.Item(j);
                        switch (pSubNode.Name)
                        {
                            case "ReportFields":
                                string strCode = null;
                                pLyr.ReportFields = GetReportfields(pSubNode, out  strCode);
                                pLyr.StatFieldName = strCode;
                                break;
                            case "Codes":
                                pLyr.StatCodes = GetStatcodes(pSubNode);
                                break;
                            case "StatField":
                                pLyr.StatFieldName = pSubNode.Attributes["Key"].Value.Trim();
                                break;
                            case "Reports":
                                pLyr.ReportNames = GetReportnames(pSubNode);
                                break;
                            default:
                                break;
                        }
                    }
                    pLyrs.Add(pLyr);
                }
                return pLyrs;
            }
            catch
            {
                return pLyrs;
            }
        }

        private  static XmlNode  GetElementByIdname(string strID,XmlDocument doc)
        {
            XmlNodeList pNodeList = doc.DocumentElement.ChildNodes ;
            foreach (XmlNode pNode in pNodeList)
            {
                if ((pNode.Name == "LayerName") && (pNode.Attributes["Key"].Value.Trim() == strID))
                    return pNode;
            }
            return null;
        }

        private static List<ReportField> GetReportfields(XmlNode pNode, out string strCode)
        {
            strCode = null;
            List<ReportField> fields = new List<ReportField>();
            if (!pNode.HasChildNodes) { return fields; }

            foreach(XmlNode pSubNode in pNode.ChildNodes)
            {
                ReportField field = new ReportField();
                field.Key = pSubNode.Attributes["Key"].Value.Trim();
                field.Desc = pSubNode.Attributes["Desc"].Value.Trim();
                field.Value = pSubNode.Attributes["Value"].Value.Trim();
                field.Type = pSubNode.Attributes["Type"].Value.Trim();
                fields.Add(field);
            }
            return fields;
        }

        private static List<StatCode> GetStatcodes(XmlNode pNode)
        {
            List<StatCode> codes = new List<StatCode>();
            if (!pNode.HasChildNodes) { return codes; }
            foreach (XmlNode pSubNode in pNode.ChildNodes)
            {
                StatCode code = new StatCode();
                code.Fcode = pSubNode.Attributes["FCODE"].Value.Trim();
                code.Value = pSubNode.Attributes["Value"].Value.Trim();
                code.Check =bool.Parse(pSubNode.Attributes["Checked"].Value.Trim());
                codes.Add(code);
            }
            return codes;
        }

        private static List<ReportName> GetReportnames(XmlNode pNode)
        {
            List<ReportName> reports = new List<ReportName>();
            if (!pNode.HasChildNodes) { return reports; }
            foreach (XmlNode pSubNode in pNode.ChildNodes)
            {
                ReportName report = new ReportName();
                report.Key = pSubNode.Attributes["Key"].Value.Trim();
                report.Value = pSubNode.Attributes["Value"].Value.Trim();
                report.HasParameter =bool.Parse(pSubNode.Attributes["HasPara"].Value);
                report.Display = bool.Parse(pSubNode.Attributes["Display"].Value);
                reports.Add(report);
            }
            return reports;
        }

    }
}
